package com.travel.server.manager.impl.command.order.data;

import com.travel.common.CommonConstant;
import com.travel.common.util.CollectionUtil;
import com.travel.common.util.CommonUtil;
import com.travel.common.util.DateUtil;
import com.travel.server.manager.dto.request.order.data.QueryOrderConstituteRequest;
import com.travel.server.manager.dto.response.order.data.QueryOrderConstituteResponse;
import com.travel.server.manager.dto.response.order.data.QueryOrderConstituteResponse.OrderAmountItem;
import com.travel.server.manager.dto.response.order.data.QueryOrderConstituteResponse.OrderConstituteItem;
import com.travel.server.manager.impl.command.AbstractCommand;
import com.travel.server.manager.impl.dal.OrderDal;
import com.travel.server.manager.impl.sal.OrderDataSal;
import com.travel.server.manager.impl.vo.DataDateVo;
import com.travel.server.manager.model.dto.data.AmountSectionDto;
import com.travel.server.manager.model.dto.data.OrderDataDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @Author: LiZhenhui
 * @Date: 2018/12/7 16:23
 * @Desc:
 */
@Component
@Slf4j
public class QueryOrderConstituteCommand extends AbstractCommand<QueryOrderConstituteRequest, QueryOrderConstituteResponse> {

    @Autowired
    private OrderDal orderDal;

    @Override
    protected void checkInput(QueryOrderConstituteRequest request) {
        checkTimeInput(request);
        if(request.getType() == null){
            throwInvalidParam();
        }
    }

    @Override
    public QueryOrderConstituteResponse handle(QueryOrderConstituteRequest request) {
        DataDateVo dateVo = OrderDataSal.getDate(request.getType(), request);
        Date startTime = dateVo.getStartTime();
        Date endTime = dateVo.getEndTime();
        Date lastTime = dateVo.getLastTime();

        QueryOrderConstituteResponse response = new QueryOrderConstituteResponse();
        response.setOrderAmountList(makeAmountList(startTime, endTime));
        response.setOrderConstituteList(makeConstitute(lastTime, endTime));
        return response;
    }

    public List<OrderConstituteItem> makeConstitute(Date startTime, Date lastTime) {
        List<OrderDataDto> list = orderDal.selectOrderData(startTime, lastTime);

        List<OrderConstituteItem> constituteList = new ArrayList<>();
        OrderConstituteItem member;
        OrderConstituteItem notMember;
        if (!CollectionUtil.isEmpty(list)) {
            int memberCurrentPayAmount = 0;
            int memberLastPayAmount = 0;
            int memberCurrentPayOrderNum = 0;
            int memberLastPayOrderNum = 0;
            int notMemberCurrentPayAmount = 0;
            int notMemberLastPayAmount = 0;
            int notMemberCurrentPayOrderNum = 0;
            int notMemberLastPayOrderNum = 0;
            for(OrderDataDto dto : list) {
                Date date = DateUtil.getDataTime(dto.getDays());
                if(date.before(startTime)){
                    if(dto.getMember().equals(CommonConstant.YES)){
                        memberLastPayAmount += dto.getPayAmount();
                        memberLastPayOrderNum += dto.getPayNum();
                    }else{
                        notMemberLastPayAmount += dto.getPayAmount();
                        notMemberLastPayOrderNum += dto.getPayNum();
                    }
                }else{
                    if(dto.getMember().equals(CommonConstant.YES)){
                        memberCurrentPayAmount += dto.getPayAmount();
                        memberCurrentPayOrderNum += dto.getPayNum();
                    }else{
                        notMemberCurrentPayOrderNum += dto.getPayNum();
                        notMemberCurrentPayAmount += dto.getPayAmount();
                    }
                }
            }
            member = makeConstituteItem(memberCurrentPayAmount, memberLastPayAmount, memberCurrentPayOrderNum, memberLastPayOrderNum, CommonConstant.YES);
            notMember = makeConstituteItem(notMemberCurrentPayAmount, notMemberLastPayAmount, notMemberCurrentPayOrderNum, notMemberLastPayOrderNum, CommonConstant.NO);
        }else{
            member = makeEmptyConstituteItem(CommonConstant.YES);
            notMember = makeEmptyConstituteItem(CommonConstant.NO);
        }
        constituteList.add(member);
        constituteList.add(notMember);
        return constituteList;
    }

    private List<OrderAmountItem> makeAmountList(Date startTime, Date endTime){
        List<OrderAmountItem> amountList = new ArrayList<>();
        List<AmountSectionDto> list = orderDal.selectAmountSection(startTime, endTime);
        if(list == null){
            list = new ArrayList<>();
        }
        for(OrderAmountEnum amountEnum : OrderAmountEnum.values()){
            OrderAmountItem item = new OrderAmountItem();
            item.setSection(amountEnum.getSection());
            item.setNum("0");
            for(AmountSectionDto dto : list){
                if(dto.getType().equals(amountEnum.getType())){
                    item.setNum(dto.getCount() + "");break;
                }
            }
            amountList.add(item);
        }
        return amountList;
    }

    private OrderConstituteItem makeEmptyConstituteItem(Integer userType){
        return makeConstituteItem(0,0,0,0,userType);
    }

    private OrderConstituteItem makeConstituteItem(Integer currentPayAmount, Integer lastPayAmount, Integer currentPayOrderNum, Integer lastPayOrderNum, Integer userType){
        OrderConstituteItem item = new OrderConstituteItem();
        item.setPayAmount(CommonUtil.fenToYuan(currentPayAmount).toString());
        item.setPayAmountCompare(OrderDataSal.getProportion(currentPayAmount, lastPayAmount));
        item.setPayOrder(currentPayOrderNum + "");
        item.setPayOrderCompare(OrderDataSal.getProportion(currentPayOrderNum, lastPayOrderNum));
        item.setPayNum(item.getPayOrder());
        item.setPayNumCompare(item.getPayOrderCompare());
        item.setUserType(userType);
        return item;
    }

    private enum OrderAmountEnum{

        /**
         *
         */
        FIRST(1, "0.0 - 16.0元"),
        SECOND(2, "16.0 - 39.0元"),
        THIRD(3, "39.0 - 338.0元"),
        FOURTH(4, "338.0 - 1462.0元"),
        FIFTH(5, "1462.0元以上"),
        ;

        private String section;

        private Integer type;

        OrderAmountEnum(Integer type, String section){
            this.type = type;
            this.section = section;
        }

        public String getSection() {
            return section;
        }

        public Integer getType() {
            return type;
        }
    }
}
